'######################################################################################
'Author  :         Sumit Gupta 
'Company :		   Vikasumit
'Date    :         22nd August 2005
'Modify Date :     22nd September 2007
'Upgrade version:  1.2
'--------------------------------------------------------------------------------------
'Working / Note on Class : 
'This is main Class for the Game enigne to work 
'Make object of this class in your game to Enable the Game Enigne 
'It include all the Logic for the Chess Game rules and Will not treat any of the 
'Graphics related call in here, It just need the location of the Position and will 
'handle all move logics, It is not related to the network or Plain game
'If you have a network game simply Pass the move that are verified by the engine or just
'simple pass it to network 
'######################################################################################

Imports VSUtility
Imports System.Math

Public Class clsGameEngine

    'Member Data 
#Region "Private Data member"

	'Class Controller Variables
    Private Const CON_CLASSVERSION As String = "1.2.20070922" 'Define the Class Version

	'Property Variables
	Private t_Logging As Boolean
	Private t_IsSelected As Boolean
	Private t_SelectedPiece As clsPiece
	Private t_SelectedPiecePosition As clsPosition

	'Logging Variable
	Private Log As clsLog

	'Game Controller Variables
    Private Board(7, 7) As clsPiece 'Main Board with All Piece position
    Private CutPiece(31) As clsPiece
    Private WKing_Pos As clsPosition    'Positon of the White King
	Private BKing_Pos As clsPosition	'Position of the Black king
    Private CurrentMove As enPieceColor 'Define/flag the move of color associated with gateway Position

    Private IsWKingmoved As Boolean 'Check whether a king moved or not
    Private IsBKingmoved As Boolean 'Check whether a king moved or not

    'Check if any of four rook move or not
    Private IsWRook1Moved As Boolean
    Private IsWRook2Moved As Boolean
    Private IsBRook1Moved As Boolean
    Private IsBRook2Moved As Boolean

	Private IsWKingChecked As Boolean	'If a White King is in Check Mode
	Private IsBkingChecked As Boolean	'If a Black King is in Check Mode
	Private ToPromotePiece As clsPiece	'Piece to Promote
	Private ToPromotePosition As clsPosition	'Position of Piece to Promote

#End Region

#Region "Public Events"

    'Event when a Piece is selected
    Public Event PieceSelected()
    'Whenever a Piece is deselected
    Public Event PieceDeselected()
    'When a Invalid move is Attempted
    Public Event InvalidMove(ByVal msg As String)
    'When a King is checked
    Public Event KingChecked(ByVal KingColor As String)
    'When a Pawn Promotion
    Public Event PawnPromoted(ByVal PieceColor As String)
    'Get a Piece
    Public Event PieceCut(ByVal piece As clsPiece)
    'Raise when a Move is successfully commited
    Public Event MoveCommited(ByVal movedata As String)
    'Raise When a Game Ends
    Public Event GameEnd(ByVal loser As enPieceColor)

#End Region

  'Member Functions

#Region "Private Initial Functions"

	'Function to Initialize Variables
	Private Sub Initialize()
		Dim i, j As Integer

		'Some Variable Initialization
		t_Logging = False

		'Logging Class Initialization
		Log = New clsLog("GameEngine", Me.ClassVersion)
		Log.DoLogging = t_Logging
		Log.AddDateTimeStamp = True

		Log.Write("In the Initialize Function")

		'initialize the board
		For i = 0 To 7
			For j = 0 To 7
				Board(i, j) = New clsPiece
			Next j
    Next i

    For i = 0 To 31
      CutPiece(i) = New clsPiece
    Next

    SetUpNewGame()
	End Sub

	'Function to Setup the New Game 
	'Place the Piece Etc
    Private Sub SetUpNewGame()
        Dim i, j As Integer
        For i = 0 To 7
            For j = 0 To 7
                Board(i, j).CopyAs(New clsPiece)
            Next
        Next

        For i = 0 To 7
            Board(0, i).Color = enPieceColor.PCWhite
            Board(1, i).Color = enPieceColor.PCWhite
            Board(1, i).Type = enPieceType.PTPawn
            Board(6, i).Color = enPieceColor.PCBlack
            Board(6, i).Type = enPieceType.PTPawn
            Board(7, i).Color = enPieceColor.PCBlack
        Next
        'Set up white pieces
        Board(0, 0).Type = enPieceType.PTRook
        Board(0, 1).Type = enPieceType.PTKnight
        Board(0, 2).Type = enPieceType.PTBishop
        Board(0, 3).Type = enPieceType.PTKing
        Board(0, 4).Type = enPieceType.PTCounselor
        Board(0, 5).Type = enPieceType.PTBishop
        Board(0, 6).Type = enPieceType.PTKnight
        Board(0, 7).Type = enPieceType.PTRook

        'setup black pieces
        Board(7, 0).Type = enPieceType.PTRook
        Board(7, 1).Type = enPieceType.PTKnight
        Board(7, 2).Type = enPieceType.PTBishop
        Board(7, 3).Type = enPieceType.PTKing
        Board(7, 4).Type = enPieceType.PTCounselor
        Board(7, 5).Type = enPieceType.PTBishop
        Board(7, 6).Type = enPieceType.PTKnight
        Board(7, 7).Type = enPieceType.PTRook

        'Setup the initial move 
        CurrentMove = enPieceColor.PCWhite
        t_IsSelected = False
        t_SelectedPiece = New clsPiece
        t_SelectedPiecePosition = New clsPosition

        IsBKingmoved = False
        IsWKingmoved = False
        IsWRook1Moved = False '(0,0)
        IsWRook2Moved = False '(0,7)
        IsBRook1Moved = False '(7,0)
        IsBRook2Moved = False '(7,7)

        IsWKingChecked = False
        IsBkingChecked = False
        ToPromotePiece = New clsPiece
        ToPromotePosition = New clsPosition
        WKing_Pos = New clsPosition
        BKing_Pos = New clsPosition

        'Get the Kings position in New Game
        GetKingPosition()
    End Sub


	'Get the Kings Position From Array and store them in given position
	Private Sub GetKingPosition()
		Dim i, j As Integer
		For i = 0 To 7
			For j = 0 To 7
				If Board(i, j).Type = enPieceType.PTKing Then
					If Board(i, j).Color = enPieceColor.PCBlack Then
						BKing_Pos.X = i
						BKing_Pos.Y = j
					ElseIf Board(i, j).Color = enPieceColor.PCWhite Then
						WKing_Pos.X = i
						WKing_Pos.Y = j
					End If
				End If
			Next
		Next
	End Sub

	'Get the Kings Position From Array and store them in given position (Overloaded)
	Private Function GetKingPosition(ByVal tmpBoard(,) As clsPiece, ByVal forColor As enPieceColor) As clsPosition
		Dim i, j As Integer
		For i = 0 To 7
			For j = 0 To 7
				If tmpBoard(i, j).Type = enPieceType.PTKing Then
					If tmpBoard(i, j).Color = enPieceColor.PCBlack AndAlso forColor = enPieceColor.PCBlack Then
						Return New clsPosition(i, j)
					ElseIf tmpBoard(i, j).Color = enPieceColor.PCWhite AndAlso forColor = enPieceColor.PCWhite Then
						Return New clsPosition(i, j)
					End If
				End If
			Next
		Next
		Return New clsPosition
	End Function

#End Region

#Region "Private Functions"

	'Make the Debugging Log File Active for Each Piece
  Private Sub EnableLogging(ByVal Status As Boolean)
    Log.DoLogging = Status
    Dim i, j As Integer
    For i = 0 To 7
      For j = 0 To 7
        Board(i, j).DoLogging = Status
      Next j
    Next i
  End Sub

  'Check if the Current Color's King is checked or not in the Given Board
  'Move is already Taken, It only Check the current game positions
  Private Function IsKingCheck(ByVal tmpBoard(,) As clsPiece, ByVal Checkfor As enPieceColor) As Boolean
    Dim i, j As Integer
    Dim tmpPosition As clsPosition
    tmpPosition = New clsPosition(GetKingPosition(tmpBoard, Checkfor))
    For i = 0 To 7
      For j = 0 To 7
        If Checkfor = enPieceColor.PCBlack Then   'Checking for the Black King Piece
          If tmpBoard(i, j).Color = enPieceColor.PCWhite AndAlso _
          tmpBoard(i, j).Move_Validator(New clsPosition(i, j), tmpPosition) AndAlso _
          Piece_Move_Validation(New clsPosition(i, j), tmpPosition, tmpBoard) Then
            Return True
          End If
        ElseIf Checkfor = enPieceColor.PCWhite Then    'Checking for White Piece
          If tmpBoard(i, j).Color = enPieceColor.PCBlack AndAlso _
            tmpBoard(i, j).Move_Validator(New clsPosition(i, j), tmpPosition) AndAlso _
            Piece_Move_Validation(New clsPosition(i, j), tmpPosition, tmpBoard) Then
            Return True
          End If
        End If
      Next
    Next
    Return False
  End Function

  'Function that work In Onjunction to the IsKingCheck, Wrapper function for IsKingCheck
  'This function move the Piece and than check for the King of same color
  Private Function IsKingCheck_BeforeMove(ByVal tmpBoard1(,) As clsPiece, ByVal Checkfor As enPieceColor, ByVal pos As clsPosition) As Boolean

    Dim tmpBoard(7, 7) As clsPiece
    Dim i, j As Integer
    For i = 0 To 7
      For j = 0 To 7
        tmpBoard(i, j) = New clsPiece(tmpBoard1(i, j))
      Next
    Next

    If Me.IsPieceSelected AndAlso tmpBoard(Me.SelectedPiecePosition.X, Me.SelectedPiecePosition.Y).Move_Validator(Me.SelectedPiecePosition, pos) Then

      'Make a blank/Null at current location
      tmpBoard(Me.SelectedPiecePosition.X, Me.SelectedPiecePosition.Y).Type = enPieceType.PTNull
      tmpBoard(Me.SelectedPiecePosition.X, Me.SelectedPiecePosition.Y).Color = enPieceColor.PCNULL

      'Make a Move to new position
      tmpBoard(pos.X, pos.Y).Type = Me.SelectedPiece.Type
      tmpBoard(pos.X, pos.Y).Color = Me.SelectedPiece.Color

      Return IsKingCheck(tmpBoard, Checkfor)
    Else
      Return False
    End If
  End Function

  'Read a Piece on Given Position
  Private Function ReadPieceonBoard(ByVal Pos As clsPosition) As clsPiece
    Dim tmpBoard As clsPiece
    tmpBoard = New clsPiece(Board(Pos.X, Pos.Y))
    Return tmpBoard
  End Function

  'Make a piece selected
  Private Sub MakePieceSelected(ByVal pos As clsPosition)
    Log.Write("MakePieceSelected :: Will Select the Piece now at Pos x::" & pos.X & " Y::" & pos.Y)
    t_SelectedPiece.CopyAs(New clsPiece(ReadPieceonBoard(pos)))
    t_SelectedPiecePosition.CopyAs(New clsPosition(pos))
    t_IsSelected = True
    Log.Write("Piece is now Marked Selected. Selected Piece is : " & vbCrLf & t_SelectedPiece.Type.ToString & _
      " " & t_SelectedPiecePosition.X & " " & t_SelectedPiecePosition.Y)
  End Sub

  'Make a Piece Unselected
  Private Sub UnselectPiece(ByVal Pos As clsPosition)
    t_SelectedPiece.CopyAs(New clsPiece)
    t_SelectedPiecePosition.CopyAs(New clsPosition)
    t_IsSelected = False
    Log.Write("Piece at position after deselection :: " & Me.ReadPieceonBoard(Pos).Type.ToString)
  End Sub

  'Function to return the Changed color of piece
  Private Function ChangeMyColor(ByVal piece As clsPiece) As enPieceColor
    If piece.Color = enPieceColor.PCNULL Then
      Return enPieceColor.PCNULL
    ElseIf piece.Color = enPieceColor.PCBlack Then
      Return enPieceColor.PCWhite
    Else
      Return enPieceColor.PCBlack
    End If
  End Function

  'Check the Move is valid in respect of Game Rules
  'One of important function for implementation of the chess rules
  Private Function IsValidMove(ByVal pos As clsPosition) As Boolean
    Log.Write("In the IsValidMove function")
    'No Piece is selected this function cannot be called here
    If Not Me.IsPieceSelected Then
      Log.Write("In IsValidMove : Not Me.IsPieceSelected ")
      RaiseEvent InvalidMove("Piece is not Selected")
      Return False
    End If

    'Same color piece at other end
    If Me.SelectedPiece.Color = Me.ReadPieceonBoard(pos).Color Then
      Log.Write("In IsValidMove : Me.SelectedPiece.Color = Me.ReadPieceonBoard(pos).Color")
      RaiseEvent InvalidMove("Same Color Piece at other end")
      Return False
    End If

    'Move is not valid according to the piece it self
    If Not Me.SelectedPiece.Move_Validator(Me.SelectedPiecePosition, pos) Then
      Log.Write("In IsValidMove : Move Validator from Piece Class Fails")
      RaiseEvent InvalidMove("Invalid Move : Piece cannot move to that location")
      Return False
    End If

    'This move make the Movers King Checked
    Dim tmpBoardClone(7, 7) As clsPiece
    Dim i, j As Integer
    For i = 0 To 7
      For j = 0 To 7
        tmpBoardClone(i, j) = New clsPiece(Board(i, j))
      Next
    Next

    If IsKingCheck_BeforeMove(tmpBoardClone, Me.CurrentMove, pos) Then
      Log.Write("In IsValidMove : King Check")
      'MsgBox("This move will make your King Checked")
      RaiseEvent InvalidMove("This move will make your King Checked")
      Return False
    End If

    'All condition has been proved correct now move to individual piece checking
    'Check for Each Piece individually
    Log.Write("In IsValidMove : In Select Case")

    Return Piece_Move_Validation(New clsPosition(Me.SelectedPiecePosition), pos, Board)
  End Function

  'Function to check the Piece Movements according to board
  Private Function Piece_Move_Validation(ByVal Curpos As clsPosition, ByVal Pos As clsPosition, ByVal tmpBd(,) As clsPiece) As Boolean
    Dim tmpBoard(7, 7) As clsPiece
    Dim ctri, j As Integer

    For ctri = 0 To 7
      For j = 0 To 7
        tmpBoard(ctri, j) = New clsPiece(tmpBd(ctri, j))
      Next
    Next

    Select Case tmpBoard(Curpos.X, Curpos.Y).Type
      Case enPieceType.PTBishop

        Return Diagonal_Movecheck(Curpos, Pos, tmpBoard)

      Case enPieceType.PTCounselor

        If Abs(Curpos.X - Pos.X) = Abs(Curpos.Y - Pos.Y) Then    'Diagonal move (Bishop type)
          Return Diagonal_Movecheck(Curpos, Pos, tmpBoard)
        Else    'Rook type move
          Return Rook_Movecheck(Curpos, Pos, tmpBoard)
        End If

      Case enPieceType.PTKing
        'TODO: Put a Seperate Function here to validate the Castling, IF Castling is validated return 
        'that else Return the normal event
        Return King_MoveCheck(Curpos, Pos, tmpBoard)

      Case enPieceType.PTKnight

        Return True

      Case enPieceType.PTPawn

        Return Pawn_MoveCheck(Curpos, Pos, tmpBoard)

      Case enPieceType.PTRook

        Return Rook_Movecheck(Curpos, Pos, tmpBoard)

      Case enPieceType.PTNull
        'Currently Not set
        Return False
    End Select
  End Function

  'Commit the Final Move and change the variables
  Private Function CommitMove(ByVal pos As clsPosition) As Boolean
    Dim tmpData As String
    Dim i As Integer

    If Not Board(pos.X, pos.Y).IsNull Then
      For i = 0 To 31
        If CutPiece(i).IsNull Then
          CutPiece(i).Color = Board(pos.X, pos.Y).Color
          CutPiece(i).Type = Board(pos.X, pos.Y).Type
                    RaiseEvent PieceCut(CutPiece(i))
          Exit For
        End If
      Next
    End If

    Log.Write("In the CommitMove ")
    'Copy Piece
    Board(pos.X, pos.Y).CopyAs(Me.ReadPieceonBoard(Me.SelectedPiecePosition))

    'Change the Move
    Me.CurrentMove = ChangeMyColor(Me.ReadPieceonBoard(Me.SelectedPiecePosition))

    tmpData = Me.SelectedPiecePosition.X.ToString & Me.SelectedPiecePosition.Y.ToString & _
    "-" & pos.X.ToString & pos.Y.ToString

    'RaiseEvent for Move Commitment
    RaiseEvent MoveCommited(tmpData)

    'Make the Old Location blank
    Dim tmpPiece As New clsPiece
    Board(Me.SelectedPiecePosition.X, Me.SelectedPiecePosition.Y).CopyAs(tmpPiece)
    UnselectPiece(pos)

  End Function

  'Check for the Pawn Promotion
  Private Function CheckPawnPromotion() As Boolean
    Dim i, j As Integer
    For i = 0 To 7
      For j = 0 To 7
        If Board(i, j).Type = enPieceType.PTPawn Then
          If i = 0 Then
            Me.ToPromotePiece.CopyAs(Board(i, j))
            Me.ToPromotePosition.CopyAs(New clsPosition(i, j))
            RaiseEvent PawnPromoted(Board(i, j).Color.ToString)
            Return True
          ElseIf i = 7 Then
            Me.ToPromotePiece.CopyAs(Board(i, j))
            Me.ToPromotePosition.CopyAs(New clsPosition(i, j))
            RaiseEvent PawnPromoted(Board(i, j).Color.ToString)
            Return True
          End If
        End If
      Next
    Next
    Return False
  End Function

  'Function to check if a Game ends or not
  'This function assume that Move has just commited by the Player i.e. called after MoveCommited
  'Now it See if that Otherplayer has any possible move that cancel the King Check If any
  'Otherwise this function is not called ;o)
  'It require that KingChecked is True for Opposing Color ;o)
  Private Function CheckForGameEnd() As Boolean
    'TODO : CheckForGameEnd
    'Currently This will not take into account for the Castle Move as the game itself doesn't implement
    'Castling 
    'Make the clone of the Chess Board 
    Dim tmpBoard(7, 7) As clsPiece
    Dim i, j As Integer
    Dim CheckForGame As Boolean
    Dim MyColor As enPieceColor
    Dim tmpPiece As clsPiece
    Dim innerI, innerJ As Integer
    Dim CurrentPos As clsPosition
    Dim LandingPos As clsPosition
    Dim GameOver As Boolean = False

    Checkforgame = False
    For i = 0 To 7
      For j = 0 To 7
        tmpBoard(i, j) = New clsPiece(Me.Board(i, j))
      Next
    Next
    'Now Check for the Piece Color
    If Me.MoveOf = enPieceColor.PCBlack Then
      If Me.IsBkingChecked Then
        CheckForGame = True
        MyColor = enPieceColor.PCBlack
      End If
    ElseIf Me.MoveOf = enPieceColor.PCWhite Then
      If Me.IsWKingChecked Then
        CheckForGame = True
        MyColor = enPieceColor.PCWhite
      End If
    Else
      'No Color Specify Virtually never come to this situation
      Return False
    End If
    'all conditions met now check for the game 
    If CheckForGame Then
      'The Long Loop that check for the Piece to see if it can break the Check Condition.. ;o)
      For i = 0 To 7
        For j = 0 To 7
          'It is not a blank case and also of my piece that Need to be simulated..
          If Not tmpBoard(i, j).IsNull And tmpBoard(i, j).Color = MyColor Then
            'Simulated the Move of the Piece if it can reach to Position...:o)
            'The loop below provide the Ending position
            CurrentPos = New clsPosition(i, j)
            tmpPiece = New clsPiece(tmpBoard(i, j))
            For innerI = 0 To 7
              For innerJ = 0 To 7

                LandingPos = New clsPosition(innerI, innerJ)
                'Piece can move to that position
                If tmpPiece.Move_Validator(CurrentPos, LandingPos) Then
                  If Me.Piece_Move_Validation(CurrentPos, LandingPos, tmpBoard) Then 'Check for Game Rules
                    Dim tmpboard1(7, 7) As clsPiece
                    Dim ctri, ctrj As Integer
                    For ctri = 0 To 7
                      For ctrj = 0 To 7
                        tmpboard1(ctri, ctrj) = New clsPiece(tmpBoard(ctri, ctrj))
                      Next
                    Next

                    tmpboard1(LandingPos.X, LandingPos.Y).Color = tmpboard1(CurrentPos.X, CurrentPos.Y).Color
                    tmpboard1(LandingPos.X, LandingPos.Y).Type = tmpboard1(CurrentPos.X, CurrentPos.Y).Type
                    tmpboard1(CurrentPos.X, CurrentPos.Y).Color = enPieceColor.PCNULL
                    tmpboard1(CurrentPos.X, CurrentPos.Y).Type = enPieceType.PTNull

                    If Me.IsKingCheck(tmpboard1, MyColor) Then
                      'TODO: Close Logging here
                      Log.DoLogging = True
                      Log.Write("currentpos.X : " & CurrentPos.X & "== currentpos.Y" & CurrentPos.Y)
                      Log.Write("Player At Position : " & tmpPiece.Type & "== color" & tmpPiece.Color)
                      Log.DoLogging = False
                      'My King is still Checked GoAhead
                      GameOver = True
                    Else
                      GameOver = False
                      Return False
                    End If
                  End If

                End If

              Next
            Next

          End If
        Next
      Next
      Return True
    Else
      'No Need to check for Game end as check is not there..;o)
      Return False
    End If
  End Function


#Region "Piece Move Validator"

  'Private function to check the diagonal move is valid or not, called by the move validtor 
  'It will not change the Board piece location
  Private Function Diagonal_Movecheck(ByVal CurPos As clsPosition, ByVal NewPos As clsPosition, ByVal tmpBoard(,) As clsPiece) As Boolean
    Dim i As Integer
    If CurPos.X < NewPos.X Then  'moving downwards
      If CurPos.Y < NewPos.Y Then   'moving right side
        For i = CurPos.X To NewPos.X
          CurPos.X += 1
          CurPos.Y += 1
          If CurPos.X = NewPos.X And CurPos.Y = NewPos.Y Then
            'We reach final position
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            'It avoid Jumping of the Piece
            Return False
          End If
        Next
      Else   'move left side
        For i = CurPos.X To NewPos.X
          CurPos.X += 1
          CurPos.Y -= 1
          If CurPos.X = NewPos.X And CurPos.Y = NewPos.Y Then
            'We reach final position
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            'It avoid Jumping of the Piece
            Return False
          End If
        Next
      End If
    Else  'move upwards
      If CurPos.Y < NewPos.Y Then   'moving right side
        For i = CurPos.X To NewPos.X Step -1
          CurPos.X -= 1
          CurPos.Y += 1
          If CurPos.X = NewPos.X And CurPos.Y = NewPos.Y Then
            'We reach final position
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            'It avoid Jumping of the Piece
            Return False
          End If
        Next
      Else   'move left side
        For i = CurPos.X To NewPos.X Step -1
          CurPos.X -= 1
          CurPos.Y -= 1
          If CurPos.X = NewPos.X And CurPos.Y = NewPos.Y Then
            'We reach final position
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            'It avoid Jumping of the Piece
            Return False
          End If
        Next
      End If
    End If
  End Function

  'Function to check the rook movement on board 
  Private Function Rook_Movecheck(ByVal CurPos As clsPosition, ByVal NewPos As clsPosition, ByVal tmpBoard(,) As clsPiece) As Boolean
    Dim i As Integer
    'Movement in the same row (right or left movement)
    If CurPos.X = NewPos.X Then
      If CurPos.Y < NewPos.Y Then   'Movement in right
        'increment one step at one time
        For i = CurPos.Y To NewPos.Y
          CurPos.Y += 1
          If CurPos.Y = NewPos.Y Then
            Return True
          End If
          If Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            Return False
          End If
        Next
      Else   'Left movement
        For i = CurPos.Y To NewPos.Y Step -1
          CurPos.Y -= 1
          If CurPos.Y = NewPos.Y Then
            Return True
          End If
          If Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            Return False
          End If
        Next
      End If
    Else  'Up and down movement
      If CurPos.X < NewPos.X Then   'down movement
        For i = CurPos.X To NewPos.X
          CurPos.X += 1
          If CurPos.X = NewPos.X Then
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            Return False
          End If
        Next
      Else   'Up movement
        For i = CurPos.X To NewPos.X Step -1
          CurPos.X -= 1
          If CurPos.X = NewPos.X Then
            Return True
          ElseIf Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
            Return False
          End If
        Next
      End If
    End If

  End Function

  'Check for the Pawn Move
  Private Function Pawn_MoveCheck(ByVal CurPos As clsPosition, ByVal NewPos As clsPosition, ByVal tmpBoard(,) As clsPiece) As Boolean

    Dim i As Integer
    Log.Write("Pawn_MoveCheck : Called")
    'Movement of the pawn
    'If the Taking is on  side move
    If (CurPos.Y - 1 = NewPos.Y Or CurPos.Y + 1 = NewPos.Y) _
    And (CurPos.X - 1 = NewPos.X Or CurPos.X + 1 = NewPos.X) _
    Then   'If side way movement
      Log.Write("Pawn_MoveCheck : If Side Move")
      If tmpBoard(NewPos.X, NewPos.Y).IsNull Then    'if empty block in side than no movement
        Return False
      Else
        'if side piece is there and with same color 
        If tmpBoard(NewPos.X, NewPos.Y).Color = tmpBoard(CurPos.X, CurPos.Y).Color Then
          Return False
          'Side kill is ok
        Else
          Return True
        End If
      End If
    Else   'not a side movement normal move one step or two step
      Log.Write("Pawn_MoveCheck : not a side move")
      Select Case tmpBoard(CurPos.X, CurPos.Y).Color
        Case enPieceColor.PCBlack
          'Pawn of black 
          For i = CurPos.X To NewPos.X Step -1
            CurPos.X -= 1       'Move decrement
            'If the final destination reached, if so is it empty 
            If CurPos.IsEqualTo(NewPos) And tmpBoard(CurPos.X, CurPos.Y).IsNull Then
              Return True
            End If

            'if block is not empty move is not allowed
            If Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
              Return False
            End If

            'It is the first movement of Pawn
            If Not CurPos.X = 5 Then
              Return False
            End If

          Next
        Case enPieceColor.PCWhite
          For i = CurPos.X To NewPos.X
            CurPos.X += 1       'move Increment
            'if the final destination reached, if so is it empty block
            If CurPos.IsEqualTo(NewPos) And tmpBoard(CurPos.X, CurPos.Y).IsNull Then
              Return True
            End If
            'if the block is not empty
            If Not tmpBoard(CurPos.X, CurPos.Y).IsNull Then
              Return False
            End If
            'if the first move
            If Not CurPos.X = 2 Then
              Return False
            End If
          Next
      End Select
    End If
  End Function

  'Check for the Kings Move
  Private Function King_MoveCheck(ByVal CurPos As clsPosition, ByVal NewPos As clsPosition, ByVal tmpBoard(,) As clsPiece) As Boolean
    Log.Write("In King_MoveCheck :")
    'Movement of the King
    If NewPos.X >= CurPos.X - 1 And NewPos.X <= CurPos.X + 1 And _
    NewPos.Y >= CurPos.Y - 1 And NewPos.Y <= CurPos.Y + 1 Then
      If Not tmpBoard(NewPos.X, NewPos.Y).IsNull Then
        If tmpBoard(NewPos.X, NewPos.Y).Color = tmpBoard(CurPos.X, CurPos.Y).Color Then
          Return False
        Else
          Return True
        End If
      Else
        'The given New position is Empty
        Return True
      End If

    ElseIf (NewPos.X = CurPos.X) And (NewPos.Y = CurPos.Y + 2 Or NewPos.Y = CurPos.Y - 2) Then
      'Castle Move
      If Me.SelectedPiece.Color = enPieceColor.PCBlack And Not IsBKingmoved Then   'Black king attempt Castle
        Return True
      ElseIf Me.SelectedPiece.Color = enPieceColor.PCWhite And Not IsWKingmoved Then   'Black king attempt Castle
        Return True
      Else
        Return False
      End If
    Else
      Return False
    End If

  End Function

#End Region

#End Region

#Region "Constructor"

	'Default Constructor
	Public Sub New()
		Initialize()
	End Sub

#End Region

#Region "Public Property "

	'Get the Class Version
	Public ReadOnly Property ClassVersion() As String
		Get
			Return CON_CLASSVERSION
		End Get
	End Property

	'Set Weather to DO logging or not
	Public Property DoLogging() As Boolean
		Get
			Return t_Logging
		End Get
		Set(ByVal Value As Boolean)
			t_Logging = Value
			Me.EnableLogging(t_Logging)
		End Set
	End Property

	'Return If a Piece is selected or not
	Public ReadOnly Property IsPieceSelected() As Boolean
		Get
			Return t_IsSelected
		End Get
	End Property

	'Return Selected Piece 
	Public ReadOnly Property SelectedPiece() As clsPiece
		Get
			Return t_SelectedPiece
		End Get
	End Property

	'Return Selected PiecePosition
	Public ReadOnly Property SelectedPiecePosition() As clsPosition
		Get
			Return t_SelectedPiecePosition
		End Get
  End Property

  'Check the Piece 
  Public ReadOnly Property MoveOf() As enPieceColor
    Get
      Dim tmpColor As enPieceColor
      tmpColor = Me.CurrentMove
      Return tmpColor
    End Get
  End Property

  Public ReadOnly Property CutLog() As clsPiece()
    Get
      Dim tmplog(31) As clsPiece
      Dim i As Integer
      For i = 0 To 31
        tmplog(i) = New clsPiece(CutPiece(i))
      Next
      Return tmplog
    End Get
  End Property

#End Region

#Region "Public Functions"

	'Setting up New Game
  Public Sub StartNewGame()
    Initialize()
  End Sub

	'Setting Up New Game (Overloaded)
  Public Sub StartNewGame(ByVal DoLog As Boolean)
    Initialize()
    Me.DoLogging = DoLog
  End Sub

	'Allow Board Position Reading
	Public Function ReadBoard() As clsPiece(,)
		Return Board
	End Function

	'Promote Pawn
  Public Function PromotePawn(ByVal PieceType As enPieceType) As Boolean

    If PieceType = enPieceType.PTNull Or PieceType = enPieceType.PTPawn _
    Or PieceType = enPieceType.PTKing Then
      Return False
    Else
      Board(Me.ToPromotePosition.X, Me.ToPromotePosition.Y).Type = PieceType
      Return True
    End If
  End Function

#Region "Gateway Functions"

  'Function to Define the move of the chess Pieces, Make a Call to this function when ever
  'GUI detect a Valid click, And it return True or False if the Position is valid in 
  'respect that, It is Valid Move, (It is not concern whether a Check is occur or Piece cannot move due to 
  'game logic etc)
  Public Function MakeMove(ByVal Pos As clsPosition) As Boolean
    Log.Write("In the GateWay Function with Pos as X::" & Pos.X & " Y::" & Pos.Y)
    ' A Null Piece Ignore it and no Piece is selected yet
    If ReadPieceonBoard(Pos).IsNull And Me.IsPieceSelected = False Then  'A Null Case is Selected
      Log.Write("In Piece is null")
      RaiseEvent InvalidMove("No Piece Found at Given Location")
      Return False
    End If

    Log.Write("After Piece Null Check")

    'Check for the Piece 
    If Me.IsPieceSelected Then  'Piece is selected Do the move Logics
      Log.Write("In Piece Is Selected")

      If Me.SelectedPiecePosition.IsEqualTo(Pos) AndAlso _
      Me.SelectedPiece.IsEqualTo(ReadPieceonBoard(Pos)) Then       'Check if the two piece are same
        'Two piece are same Deselect the Piece
        UnselectPiece(Pos)
        RaiseEvent PieceDeselected()
        Log.Write("Piece Deselected")
        Return True
      End If

      If Me.IsValidMove(Pos) Then   'It is Valid Move in Respect of a Piece
        Log.Write("It is valid Move")
        'Commit the move
        'Mark the White King Move
        If Not Me.IsWKingmoved AndAlso _
        Me.ReadPieceonBoard(Me.SelectedPiecePosition).Type = enPieceType.PTKing AndAlso _
        Me.ReadPieceonBoard(Me.SelectedPiecePosition).Color = enPieceColor.PCWhite Then
          Me.IsWKingmoved = True
        End If
        'Mark the Black King Moved
        If Not Me.IsBKingmoved AndAlso _
        Me.ReadPieceonBoard(Me.SelectedPiecePosition).Type = enPieceType.PTKing AndAlso _
        Me.ReadPieceonBoard(Me.SelectedPiecePosition).Color = enPieceColor.PCBlack Then
          Me.IsBKingmoved = True
        End If

        'Now My King is not Checked
        If Me.CurrentMove = enPieceColor.PCBlack Then
          'Black King is checked
          Me.IsBkingChecked = False
        ElseIf Me.CurrentMove = enPieceColor.PCWhite Then
          'White King is checked
          Me.IsWKingChecked = False
        End If
        Log.Write("About to commit the move")

        'Check similarly for the Rook
        CommitMove(Pos)    'Move Change here

        Log.Write("Move committed")

        'Check for Pawn Promition if True than RaiseEvent for the Same and 
        'User Interface will change the promote Pawn
        CheckPawnPromotion()

        'Check if Opposing king is checked or not

        If Me.IsKingCheck(Board.Clone, Me.CurrentMove) Then
          'King is checked
          'Not sure why I have PCWhite here ?
          'RaiseEvent KingChecked(Me.CurrentMove.PCWhite)
          'So correct that below
          RaiseEvent KingChecked(Me.CurrentMove.ToString)
          'Opposing King is Now Checked
          If Me.CurrentMove = enPieceColor.PCBlack Then
            'Black King is checked
            Me.IsBkingChecked = True
          ElseIf Me.CurrentMove = enPieceColor.PCWhite Then
            'White King is checked
            Me.IsWKingChecked = True
          End If
        End If

        'Here come the Game End Check
        If CheckForGameEnd() Then
          RaiseEvent GameEnd(Me.MoveOf)
          Return True
        End If

      Else
        'Error in the Move
        RaiseEvent InvalidMove("You cannot move your Piece there")
        Log.Write("Invalid Move")
        Return False
      End If

    Else   'Piece is not Selected Select the Piece
      Log.Write("In Piece is not Selected")
      If ReadPieceonBoard(Pos).IsNull Then   ' Same as first check and this code will never be called 
        'Just to mark the check is required here
        RaiseEvent InvalidMove("No Piece Found at Given Location")
        Return False
      End If
      'Select the Piece
      If Me.CurrentMove = Me.ReadPieceonBoard(Pos).Color Then
        MakePieceSelected(Pos)
        RaiseEvent PieceSelected()
        Return True
      Else
        RaiseEvent InvalidMove("Attempt to capture Wrong Color Piece")
        Return False
      End If
    End If
    'Every thing Seems ok Return Positive Answer
    Return True
  End Function

#End Region

#End Region

End Class